package com.gitee.l0km.aocache.config;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;

import com.gitee.l0km.aocache.AocacheRemovalListener;
import com.gitee.l0km.aocache.AocacheRemovalListener.AocacheRemovalNotification;
import com.google.common.cache.RemovalListener;
import com.google.common.cache.RemovalNotification;

/**
 * <p>
 * {@code RemovalListenerWrapper} 类是一个包装器类，用于将 {@link AocacheRemovalListener} 包装成 Google Guava 缓存所需的 {@link RemovalListener}。<br>
 * 该类提供了多种静态方法，用于根据不同的输入（如对象实例、类类型、类名）来创建包装后的监听器实例。
 * </p>
 * 
 * @param <K> 缓存键的类型
 * @param <V> 缓存值的类型
 */
class RemovalListenerWrapper<K, V> implements RemovalListener<K, V> {
	private final AocacheRemovalListener<K, V> listener;

	private RemovalListenerWrapper(AocacheRemovalListener<K, V> listener) {
		this.listener = listener;
	}

	@Override
	public void onRemoval(RemovalNotification<K, V> notification) {
		listener.onRemoval(AocacheRemovalNotification.create(notification));
	}

	@SuppressWarnings("unchecked")
	static <K, V> RemovalListener<K, V> wrap(Object listener) {
		return listener instanceof AocacheRemovalListener
				? new RemovalListenerWrapper<K, V>((AocacheRemovalListener<K, V>) listener)
				: null;
	}

	@SuppressWarnings("unchecked")
	static <K, V> RemovalListener<K, V> wrap(Class<?> listenerClass) {
		if (null != listenerClass && AocacheRemovalListener.class != listenerClass
				&& AocacheRemovalListener.class.isAssignableFrom(listenerClass)
				&& !Modifier.isAbstract(listenerClass.getModifiers())) {
			try {
				AocacheRemovalListener<K, V> listener = (AocacheRemovalListener<K, V>) listenerClass.getConstructor()
						.newInstance();
				return wrap(listener);
			} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
					| InvocationTargetException | NoSuchMethodException | SecurityException e) {
				// DO NOTHING
			}
		}
		return null;
	}

	static <K, V> RemovalListener<K, V> wrap(String listenerClassName) {
		if ((null != listenerClassName && !listenerClassName.isEmpty())) {
			try {
				return wrap(Class.forName(listenerClassName));
			} catch (ClassNotFoundException e) {
				// DO NOTHING
			}
		}
		return null;
	}
}
